syntax = "proto3";

package kuma.mesh.v1alpha1;

option go_package = "github.com/kumahq/kuma/api/mesh/v1alpha1";

import "api/mesh/options.proto";
import "api/mesh/v1alpha1/selector.proto";
import "api/mesh/v1alpha1/http_method.proto";

import "google/protobuf/duration.proto";
import "google/protobuf/wrappers.proto";
import "validate/validate.proto";
import "kuma-doc/config.proto";

option (doc.config) = {
  type : Policy,
  name : "Retry",
  file_name : "retry"
};

// These options correspond with the retry_on options in Envoy's documentation:
// https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/router_filter#config-http-filters-router-x-envoy-retry-on
enum HttpRetryOn {
  all_5xx = 0;
  gateway_error = 1;
  reset = 2;
  connect_failure = 3;
  envoy_ratelimited = 4;
  retriable_4xx = 5;
  refused_stream = 6;
  retriable_status_codes = 7;
  retriable_headers = 8;
  http3_post_connect_failure = 9;
}

message Retry {

  option (kuma.mesh.resource).name = "RetryResource";
  option (kuma.mesh.resource).type = "Retry";
  option (kuma.mesh.resource).package = "mesh";
  option (kuma.mesh.resource).kds.send_to_zone = true;
  option (kuma.mesh.resource).ws.name = "retry";
  option (kuma.mesh.resource).ws.plural = "retries";
  option (kuma.mesh.resource).allow_to_inspect = true;

  // List of selectors to match dataplanes that retry policy should be
  // configured for
  repeated Selector sources = 1
      [ (validate.rules).repeated .min_items = 1, (doc.required) = true ];

  // List of selectors to match services that need to be health checked.
  repeated Selector destinations = 2
      [ (validate.rules).repeated .min_items = 1, (doc.required) = true ];

  message Conf {
    message BackOff {
      //  +required
      google.protobuf.Duration base_interval = 1 [ (doc.required) = true ];
      //  +optional
      google.protobuf.Duration max_interval = 2;
    }

    message Http {
      //  +optional
      google.protobuf.UInt32Value num_retries = 2;

      //  +optional
      google.protobuf.Duration per_try_timeout = 3;

      //  +optional
      BackOff back_off = 4;

      //  +optional
      repeated uint32 retriable_status_codes = 5;

      //  +optional
      repeated HttpMethod retriable_methods = 6;

      //  +optional
      repeated HttpRetryOn retry_on = 7;
    }

    message Tcp {
      //  +optional
      uint32 max_connect_attempts = 1;
    }

    message Grpc {
      enum RetryOn {
        cancelled = 0;
        deadline_exceeded = 1;
        internal = 2;
        resource_exhausted = 3;
        unavailable = 4;
      }

      //  +optional
      repeated RetryOn retry_on = 1;

      //  +optional
      google.protobuf.UInt32Value num_retries = 2;

      //  +optional
      google.protobuf.Duration per_try_timeout = 3;

      //  +optional
      BackOff back_off = 4;
    }

    Http http = 1;
    Tcp tcp = 2;
    Grpc grpc = 3;
  }

  //  +required
  Conf conf = 3 [ (doc.required) = true ];
}
